#include "../include/Grass.h"
#include <iostream>
Grass::Grass(std::string filename, std::string alphaFilename) {

    texID = CG::loadTexture(filename);
    alphaID = CG::loadTexture(alphaFilename);
    Vertex *vertices = new Vertex[6];

    //set normals to point in the +y direction
    for(int i=0; i< 6 ;i++){
        vertices[i].normal[0] = 0;
        vertices[i].normal[1] = 1;
        vertices[i].normal[2] = 0;
    }

    //Bottom left corner
    vertices[0].position[0] = -0.5;
    vertices[0].position[1] = 0;
    vertices[0].position[2] = 0;
    vertices[0].texCoords[0] = 0;
    vertices[0].texCoords[1] = 1;
    //Bottom centre
    vertices[1].position[0] = 0;
    vertices[1].position[1] = 0;
    vertices[1].position[2] = 0;
    vertices[1].texCoords[0] = 0.5;
    vertices[1].texCoords[1] = 1;
    //Bottom right corner
    vertices[2].position[0] = 0.5;
    vertices[2].position[1] = 0;
    vertices[2].position[2] = 0;
    vertices[2].texCoords[0] = 1;
    vertices[2].texCoords[1] = 1;
    //Top right corner
    vertices[3].position[0] = 0.5;
    vertices[3].position[1] = 1;
    vertices[3].position[2] = 0;
    vertices[3].texCoords[0] = 1;
    vertices[3].texCoords[1] = 0;
    //Top centre
    vertices[4].position[0] = 0;
    vertices[4].position[1] = 1;
    vertices[4].position[2] = 0;
    vertices[4].texCoords[0] = 0.5;
    vertices[4].texCoords[1] = 0;
    //Top left corner
    vertices[5].position[0] = -0.5;
    vertices[5].position[1] = 1;
    vertices[5].position[2] = 0;
    vertices[5].texCoords[0] = 0;
    vertices[5].texCoords[1] = 0;

    ind1 = new GLuint[12];
    ind1[0] = 0; ind1[1] = 1; ind1[2] = 5; ind1[3] = 5; ind1[4] = 1; ind1[5] = 4;
    ind1[6] = 1; ind1[7] = 2; ind1[8] = 4; ind1[9] = 4; ind1[10] = 2; ind1[11] = 3;
    ind2 = new GLuint[12];
    ind2[0] = 1; ind2[1] = 2; ind2[2] = 4; ind2[3] = 4; ind2[4] = 2; ind2[5] = 3;
    ind2[6] = 0; ind2[7] = 1; ind2[8] = 5; ind2[9] = 5; ind2[10] = 1; ind2[11] = 4;

    //Send vertex data to GPU
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*6, NULL, GL_STATIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex)*6, vertices);

    glGenBuffers(1, &indexID);
//    //Send index data to GPU
//    glGenBuffers(1, &indexID);
//    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexID);
//    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6, NULL, GL_STATIC_DRAW);
//    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*6, indices);
    delete[] vertices;

    //Create shader
    shaderProg = CG::setupShader("resources/shaders/grass.vert", "resources/shaders/grass.frag");
}

void Grass::setupIndices(vec3 camPos, vec3 grassPos, GLfloat rotateAngle) {
    vec3 face1;
    vec3 face2;
    GLfloat dx = 0;
    GLfloat dz = 0;


    if(rotateAngle != 0){
        if(rotateAngle == 60) {
            dx = 0.25;
            dz = 0.25;
        } else if(rotateAngle == 120) {
            dx = 0.75;
            dz = 0.25;
        }
    }
    //std::cout << dx << " " << dz << std::endl;

    face1.x = (grassPos.x-0.25)+dx;
    face1.y = (grassPos.y+0.5);
    face1.z = (grassPos.z)+dz;
    face2.x = (grassPos.x+0.25)-dx;
    face2.y = (grassPos.y+0.5);
    face2.z = (grassPos.z)-dz;

    if(CG::euclidDistance(camPos, face1) <= CG::euclidDistance(camPos, face2)) {
        //Send index data to GPU
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*12, NULL, GL_STATIC_DRAW);
        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*12, ind2);

    } else {
        //Send index data to GPU
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*12, NULL, GL_STATIC_DRAW);
        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*12, ind1);
      }
}

void Grass::render(vec3 camPos, vec3 grassPos) {

    if(CG::euclidDistance(camPos, grassPos) >= 75) {
        return;
    }
    glUseProgram(shaderProg);

    //Setup texture
    CG::setTextureUnit(shaderProg, "tex", 0);
    CG::setTextureUnit(shaderProg, "alpha", 1);
    glEnable(GL_TEXTURE_2D);
    CG::bindTexture(texID, GL_TEXTURE0);
    CG::bindTexture(alphaID, GL_TEXTURE1);

    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexID);

    //Send texture coords
    glClientActiveTexture(GL_TEXTURE0);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(24));

    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);
    glNormalPointer(GL_FLOAT, sizeof(Vertex),  BUFFER_OFFSET(12));
    glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));

    glDisable(GL_CULL_FACE);
    //glDisable(GL_DEPTH_TEST);
    glDepthMask(false);
    setupIndices(camPos, grassPos,0.0);
    glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
    glPushMatrix();
    glRotatef(60, 0, 1, 0);
    setupIndices(camPos, grassPos,60);
    glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
    glRotatef(60, 0, 1, 0);
    setupIndices(camPos, grassPos,120);
    glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
    std::cout << "Drawing grass at: " << grassPos.x << " " << grassPos.y << " " << grassPos.z << std::endl;
    glPopMatrix();
    glDepthMask(true);
    //glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisable(GL_TEXTURE_2D);
}
